package dao.hibernate;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.iterators.EntrySetMapIterator;
import org.hibernate.Query;

import util.Util;

import model.BaiViet;
import model.ChuDe;
import model.NguoiDung;
import dao.BaiVietDAO;

public class BaiVietDAOHibernate extends GenericHibernateDAO<BaiViet, Long>
		implements BaiVietDAO {
	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllBaiVietChuDeKhac() {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery("SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.chuDeCha.loai = :pname")
		.setString("pname", "Chủ đề khác");
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			Date ngayDang = (Date)row[3];
			NguoiDung nguoiDang = (NguoiDung)row[4];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, null, null, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllBaiVietByIdLoaiChuDeKhac(long idLoaiChuDeKhac) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.idChuDe = :pname ORDER BY baiViet.ngayDang DESC")
		.setLong("pname", idLoaiChuDeKhac);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByIdNguoiDangLike(String userId) {
		return getSession()
				.createQuery(
						"FROM BaiViet AS baiViet WHERE baiViet.nguoiDang.idNguoiDung LIKE :pname")
				.setString("pname", "%" + userId + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByTenNguoiDangLike(String name) {
		return getSession()
				.createQuery(
						"FROM BaiViet AS baiViet WHERE baiViet.nguoiDang.hoTen LIKE :pname")
				.setString("pname", "%" + name + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByTenChuDeLike(String name) {
		return getSession()
				.createQuery(
						"SELECT baiViet FROM BaiViet AS baiViet JOIN baiViet.chuDe AS chuDe WHERE chuDe.tenChuDe LIKE :pname")
				.setString("pname", "%" + name + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByTieuDeLike(String name) {
		return getSession()
				.createQuery(
						"FROM BaiViet AS baiViet WHERE baiViet.tieuDe LIKE :pname")
				.setString("pname", "%" + name + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByNgayDangLike(String date) {
		return getSession()
				.createQuery(
						"FROM BaiViet AS baiViet WHERE baiViet.ngayDang LIKE :pname")
				.setString("pname", "%" + date + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByNoiDungLike(String noiDung) {
		return getSession()
				.createQuery(
						"FROM BaiViet AS baiViet WHERE baiViet.noiDung LIKE :pname")
				.setString("pname", "%" + noiDung + "%").list();
	}

	public List<BaiViet> findByOneCondition(String criteria, String keyWord) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		if (criteria.equals("tenChuDe")) {
			list = findByTenChuDeLike(keyWord);
		} else if (criteria.equals("tieuDe")) {
			list = findByTieuDeLike(keyWord);
		} else if (criteria.equals("idNguoiDang")) {
			list = findByIdNguoiDangLike(keyWord);
		} else if (criteria.equals("ngayDang")) {
			list = findByNgayDangLike(keyWord);
		} else if (criteria.equals("noiDung")) {
			list = findByNoiDungLike(keyWord);
		}
		
		List<BaiViet> result = new ArrayList<BaiViet>();
		BaiViet baiVietSimple = null;
		for (BaiViet baiViet : list) {
			NguoiDung nguoiDang = baiViet.getNguoiDang();
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiVietSimple = new BaiViet(baiViet.getChuDe(), baiViet.getTieuDe(), null, null, baiViet.getNgayDang(), nguoiDang, null, 0, null);
			baiVietSimple.setIdBaiViet(baiViet.getIdBaiViet());
			result.add(baiVietSimple);
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByIdNguoiDang(String idNguoiDang) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery("SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.nguoiDang.idNguoiDung = :pname")
		.setString("pname", idNguoiDang);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String URLHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, URLHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findBaiVietMoi(int soBaiViet) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet ORDER BY baiViet.ngayDang DESC")
		.setFirstResult(0).setMaxResults(soBaiViet);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findBaiVietXemNhieu(int soBaiViet) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet ORDER BY baiViet.soLanXem DESC")
		.setFirstResult(0)
		.setMaxResults(soBaiViet);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findBaiVietByIdChuDe(long idChuDe, int soBaiViet) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.idChuDe = :pid ORDER BY baiViet.soLanXem DESC")
		.setLong("pid", idChuDe)
		.setFirstResult(0)
		.setMaxResults(soBaiViet);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByKeyword(String keyword) {
		return getSession()
				.createQuery(
						"SELECT baiViet FROM BaiViet AS baiViet JOIN baiViet.chuDe AS chuDe WHERE chuDe.tenChuDe LIKE :pname OR "
								+ "baiViet.tieuDe LIKE :pname OR "
								+ "baiViet.ngayDang LIKE :pname OR "
								+ "baiViet.noiDung LIKE :pname")
				.setString("pname", "%" + keyword + "%").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findByManyConditions(MultiMap conditions) {
		List<BaiViet> result = null;
		EntrySetMapIterator iterator = new EntrySetMapIterator(conditions);
		String criteria = "";
		List<String> keywords = new ArrayList<String>();
		String keyword = "";
		while (iterator.hasNext()) {
			criteria = (String) iterator.next();
			keywords = (ArrayList<String>) conditions.get(criteria);
			for (String k : keywords) {
				keyword = k;
				if (criteria.equals("tenBaiViet")) {
					List<BaiViet> list = findByTenChuDeLike(keyword);
					result = Util.retainAllBaiViet(result, list);
				} else if (criteria.equals("tieuDe")) {
					List<BaiViet> list = findByTieuDeLike(keyword);
					result = Util.retainAllBaiViet(result, list);
				} else if (criteria.equals("noiDung")) {
					List<BaiViet> list = findByNoiDungLike(keyword);
					result = Util.retainAllBaiViet(result, list);
				} else if (criteria.equals("tenNguoiDang")) {
					List<BaiViet> list = findByTenNguoiDangLike(keyword);
					result = Util.retainAllBaiViet(result, list);
				} else if (criteria.equals("ngayDang")) {
					List<BaiViet> list = findByNgayDangLike(keyword);
					result = Util.retainAllBaiViet(result, list);
				}
			}
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllBaiVietMoiByLoaiChuDeKhac(String loaiChuDeKhac,
			int soBaiViet) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.tenChuDe = :pname ORDER BY baiViet.ngayDang DESC")
		.setString("pname", loaiChuDeKhac)
		.setFirstResult(0)
		.setMaxResults(soBaiViet);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllBaiVietMoiByLoaiChuDeKhac(String loaiChuDeKhac, String nameLike,
			int soBaiViet) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.tenChuDe = :pchude AND baiViet.tieuDe LIKE :pname ORDER BY baiViet.ngayDang DESC")
		.setString("pchude", loaiChuDeKhac)
		.setString("pname", "%" + nameLike + "%")
		.setFirstResult(0)
		.setMaxResults(soBaiViet);
		System.out.println(query.getQueryString());
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllBaiVietMoiByLoaiChuDe(String loaiChuDeKhac) {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery(
				"SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.tomTat, baiViet.URLHinh, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet WHERE baiViet.chuDe.tenChuDe = :pname ORDER BY baiViet.ngayDang DESC")
		.setString("pname", loaiChuDeKhac);
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			String tomTat = (String)row[3];
			String urlHinh = (String)row[4];
			Date ngayDang = (Date)row[5];
			NguoiDung nguoiDang = (NguoiDung)row[6];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, tomTat, urlHinh, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<BaiViet> findAllSimple() {
		List<BaiViet> list = new ArrayList<BaiViet>();
		Query query = getSession().createQuery("SELECT baiViet.idBaiViet, baiViet.chuDe, baiViet.tieuDe, baiViet.ngayDang, baiViet.nguoiDang FROM BaiViet AS baiViet");
		Iterator iter = query.list().iterator();
		BaiViet baiViet = null;
		while(iter.hasNext()){
			Object[] row = (Object[])iter.next();
			long idBaiViet = (Long)row[0];
			ChuDe chuDe = (ChuDe)row[1];
			String tieuDe = (String)row[2];
			Date ngayDang = (Date)row[3];
			NguoiDung nguoiDang = (NguoiDung)row[4];
			nguoiDang = new NguoiDung(nguoiDang.getIdNguoiDung(), null, null, nguoiDang.getHoTen(), nguoiDang.getEmail());
			baiViet = new BaiViet(chuDe, tieuDe, null, null, ngayDang, nguoiDang, null, 0, null);
			baiViet.setIdBaiViet(idBaiViet);
			list.add(baiViet);
		}
		return list;
	}

}
